package cn.stylefeng.guns.sys.modular.system.quartz.task;

import cn.hutool.core.collection.CollectionUtil;
import cn.stylefeng.guns.sys.core.util.DingdingUtil;
import cn.stylefeng.guns.sys.core.util.UUIDUtils;
import cn.stylefeng.guns.sys.modular.system.db7.model.result.DgdReemployResult;
import cn.stylefeng.guns.sys.modular.system.db7.service.DgdReemployService;
import cn.stylefeng.guns.sys.modular.system.entity.BtyReemploy;
import cn.stylefeng.guns.sys.modular.system.entity.Dict;
import cn.stylefeng.guns.sys.modular.system.model.result.ArchivesResult;
import cn.stylefeng.guns.sys.modular.system.service.ArchivesService;
import cn.stylefeng.guns.sys.modular.system.service.BtyReemployService;
import cn.stylefeng.guns.sys.modular.system.service.DictService;
import cn.stylefeng.roses.core.util.ToolUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dingtalk.api.response.OapiSmartworkHrmEmployeeV2ListResponse;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 再次入职员工信息筛选定时器
 *
 * @author: tianzhen
 * @date: 2022/5/5 16:57
 */
@Component
@Slf4j
public class ReemployEmpDataJob {

    @Resource
    private DictService dictService;
    @Resource
    private DingdingUtil dingdingUtil;
    @Resource
    private ArchivesService archivesService;
    @Resource
    private BtyReemployService btyReemployService;
    @Resource
    private DgdReemployService dgdReemployService;

    /**
     * 每天凌晨3点获取前几天的入职员工数据
     */
    @XxlJob("reemployEmpDataJob")
    public void reemployEmpFilter() {
        try {
            log.info("-----------------再次入职员工筛选定时器开始-----------------");
            //过滤前几天的入职员工数据的天数，默认7
            int dayNum = this.getDayNum();
            //获取前几天的入职员工钉钉编号(半天妖)
            List<BtyReemploy> reemploys = btyReemployService.getEntryEmpList(dayNum);
            //获取前几天的入职员工钉钉编号(东更道)
            List<DgdReemployResult> dgdReemploys = dgdReemployService.getEntryEmpList(dayNum);
            //合并数据
            if (CollectionUtil.isNotEmpty(dgdReemploys)) {
                for (DgdReemployResult info : dgdReemploys) {
                    BtyReemploy reemploy = new BtyReemploy();
                    ToolUtil.copyProperties(info, reemploy);
                    reemploys.add(reemploy);
                }
            }
            //数据处理
            List<ArchivesResult> archivesResults = this.reemployEmpDataHandle(reemploys);
            if(CollectionUtil.isNotEmpty(archivesResults)){
                List<BtyReemploy> reemployList = new ArrayList<>();
                for(ArchivesResult info : archivesResults){
                    for(BtyReemploy reemploy : reemploys){
                        if((StringUtils.isNotBlank(info.getSfz()) && info.getSfz().equals(reemploy.getIdentifyCard()))
                                || (StringUtils.isNotBlank(info.getTel()) && info.getTel().equals(reemploy.getTelephone()))){
                            //防止一个人有二次以上的离职记录，导致reemployList中出现id重复的数据
                            BtyReemploy btyReemploy = new BtyReemploy();
                            ToolUtil.copyProperties(reemploy, btyReemploy);
                            btyReemploy.setId(UUIDUtils.getUUID());
                            btyReemploy.setOriginalEntryDate(info.getRq());
                            btyReemploy.setOriginalEntryStore(info.getDm());
                            btyReemploy.setOriginalOperationsManagerInfo(info.getYhk());
                            btyReemploy.setReempStatus(1);
                            if(StringUtils.isNotBlank(info.getBz()) && info.getBz().length() > 8){
                                String leaveDateStr = info.getBz().substring(info.getBz().length()-8);
                                if(StringUtils.isNumeric(leaveDateStr)){
                                    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
                                    btyReemploy.setLeaveDate(sdf.parse(leaveDateStr));
                                    //离职日期必须在新入职日期之前（员工表中状态更新不及时）
                                    if(btyReemploy.getLeaveDate().after(btyReemploy.getEntryDate())){
                                        break;
                                    }
                                }
                            }
                            reemployList.add(btyReemploy);
                            break;
                        }
                    }
                }
                if(CollectionUtil.isNotEmpty(reemployList)){
                    btyReemployService.addList(reemployList);
                }
            }
            log.info("-----------------再次入职员工筛选定时器结束-----------------");
        } catch (Exception e) {
            log.info("再次入职员工定时器新增数据失败：{}", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 根据入职员工获取是否存在离职记录并在是否在表中已存在
     *
     * @param:  reemploys 入职员工集合
     * @return: archivesResults 符合条件的入职员工集合
     */
    private List<ArchivesResult> reemployEmpDataHandle(List<BtyReemploy> reemploys) {
        if (CollectionUtil.isNotEmpty(reemploys)) {
            //通过钉钉编号获取员工的身份证号
            this.getIdentifyCardByDingding(reemploys);
            //sql 拼接in最多1000个
            List<ArchivesResult> archivesResults = new ArrayList<>();
            List<ArchivesResult> dgdLeaveEmpList = new ArrayList<>();

            List<BtyReemploy> tempList = new ArrayList<>(512);
            for(int i = 1; i <= reemploys.size(); i++){
                tempList.add(reemploys.get(i-1));
                if(i%900 == 0 || i == reemploys.size()){
                    //查询再次入职的员工集合（sql排除掉再次入职表中已存在的数据）(半天妖)
                    List<ArchivesResult> btyArchivesResults = archivesService.getLeaveEmpList(tempList);
                    //查询再次入职的员工集合（跨库不能sql过滤）(东更道)
                    List<ArchivesResult> dgdArchivesResults = dgdReemployService.getLeaveEmpList(tempList);
                    if(CollectionUtil.isNotEmpty(btyArchivesResults)){
                        archivesResults.addAll(btyArchivesResults);
                    }
                    if(CollectionUtil.isNotEmpty(dgdArchivesResults)){
                        dgdLeaveEmpList.addAll(dgdArchivesResults);
                    }
                    tempList.clear();
                }
            }
            if (CollectionUtil.isNotEmpty(dgdLeaveEmpList)) {
                //判断在表中是否已经存在
                List<BtyReemploy> existReemploys = btyReemployService.existReemployEmpList(dgdLeaveEmpList);
                if (CollectionUtil.isNotEmpty(existReemploys)) {
                    for (ArchivesResult archivesResult : dgdLeaveEmpList) {
                        boolean notExistFlag = true;
                        for (BtyReemploy info : existReemploys) {
                            //身份证号并且入职日期没有在原入职日期之后都判定已经存在
                            if (StringUtils.isBlank(archivesResult.getSfz()) || ((ObjectUtils.nullSafeEquals(info.getIdentifyCard(), archivesResult.getSfz())
                                    || ObjectUtils.nullSafeEquals(info.getTelephone(), archivesResult.getTel())) && !archivesResult.getRq().after(info.getOriginalEntryDate()))) {
                                notExistFlag = false;
                                break;
                            }
                        }
                        if (notExistFlag) {
                            archivesResults.add(archivesResult);
                        }
                    }
                } else {
                    archivesResults.addAll(dgdLeaveEmpList);
                }
            }
            archivesResults.sort((x1, x2) -> {return (x1.getRq().after(x2.getRq()) ? 1 : -1);});
            Map<String, ArchivesResult> tempMap = archivesResults.stream().collect(Collectors.toMap(item -> (item.getSfz() + item.getTel()), Function.identity(), (o, n) -> n));
            archivesResults = new ArrayList<>(tempMap.values());
            return archivesResults;
        }
        return null;
    }

    /**
     * 过滤前几天的入职员工数据的天数，默认7
     *
     * @param:
     * @return: int 天数
     */
    private int getDayNum(){
        int dayNum = 7;
        Dict dict = dictService.getOne(new QueryWrapper<Dict>().eq("code", "day_num_week"));
        if (dict != null && StringUtils.isNumeric(dict.getName())) {
            dayNum = Integer.parseInt(dict.getName());
        }
        return dayNum;
    }

    /**
     * 过滤前几天的入职员工数据的天数，默认7
     *
     * @param: reemploys 入职职员数据集合
     * @return:
     */
    private void getIdentifyCardByDingding(List<BtyReemploy> reemploys){
        //拼接员工钉钉userid字符串
        Map<String, String> cardMap = new HashMap<>(512);
        //钉钉花名册接口，编号最多传100个
        StringBuffer empNumsBuf = new StringBuffer();
        for(int i = 1; i <= reemploys.size(); i++){
            empNumsBuf.append(reemploys.get(i-1).getReempNum()).append(",");
            if(i%100 == 0 || i == reemploys.size()){
                String empNumsStr = empNumsBuf.delete(empNumsBuf.length() - 1, empNumsBuf.length()).toString();
                List<OapiSmartworkHrmEmployeeV2ListResponse.EmpRosterFieldVo> rotaInfoList = dingdingUtil.getRotaInfoList(empNumsStr);
                //获取员工编号对应的身份账号，暂存到map中
                for(OapiSmartworkHrmEmployeeV2ListResponse.EmpRosterFieldVo info : rotaInfoList){
                    String userNum = info.getUserid();
                    List<OapiSmartworkHrmEmployeeV2ListResponse.EmpFieldDataVo> fieldDataList = info.getFieldDataList();
                    if(CollectionUtil.isNotEmpty(fieldDataList)){
                        String dentifyCard = fieldDataList.get(0).getFieldValueList().get(0).getValue();
                        cardMap.put(userNum, dentifyCard);
                    }
                }
                empNumsBuf.setLength(0);
            }
        }
        //入职员工信息集合设置身份证号
        reemploys.stream().map(item -> {item.setIdentifyCard(cardMap.get(item.getReempNum())); return item;}).collect(Collectors.toList());
    }



}